﻿
Imports System.Runtime.CompilerServices

Namespace std
    Public Interface ikeyvalue(Of keyT As IComparable(Of keyT), valueT)

    End Interface

    Public Module keyvalue_extension
        <Extension()> Public Function random_key(Of keyT As IComparable(Of keyT), valueT) _
                                                (ByVal this As keyvalue(Of keyT, valueT)) As keyT
            assert(Not this Is Nothing)
            Dim rtn As keyT = Nothing
            Dim count As Int64 = 0
            If this.foreach(Function(ByRef key As keyT,
                                     ByRef v As valueT,
                                     ByRef goon As Boolean) As Boolean
                                count += 1
                                If rnd_int(0, count) = 0 Then
                                    rtn = key
                                End If
                                goon = True
                                Return True
                            End Function) Then
                assert(count = 0 OrElse Not rtn Is Nothing)
                Return rtn
            Else
                Return Nothing
            End If
        End Function
    End Module

    Public Class keybytes(Of keyT As IComparable(Of keyT))
        Inherits keyvalue(Of keyT, bytes)

        Public Sub New(ByVal m As map(Of keyT, bytes))
            MyBase.New(m)
        End Sub

        Public Sub New()
            MyBase.New()
        End Sub

        Protected Overrides Function append(ByVal this As bytes, ByVal that As bytes) As bytes
            Return this + that
        End Function

        Protected Overrides Function sizeof(ByVal v As bytes) As Int64
            If v Is Nothing Then
                Return 0
            Else
                Return v.size()
            End If
        End Function
    End Class

    Public Class keyvalue(Of keyT As IComparable(Of keyT), valueT)
        Private ReadOnly m As map(Of keyT, valueT) = Nothing
        Private value_size As Int64 = 0
        Private wl As singleentry
        Private rl As singleentry

        Public Sub New(ByVal m As map(Of keyT, valueT))
            If m Is Nothing Then
                Me.m = New map(Of keyT, valueT)()
            Else
                copy(Me.m, m)
            End If
            assert(Not read_locked())
            assert(Not write_locked())
        End Sub

        Public Sub New()
            Me.New(Nothing)
        End Sub

        Private Sub lock(ByRef i As singleentry)
            i.mark_in_use()
        End Sub

        Private Sub lock_write()
            lock(wl)
        End Sub

        Private Sub lock_read()
            lock(rl)
        End Sub

        Private Sub unlock(ByRef i As singleentry)
            i.mark_not_in_use()
        End Sub

        Private Sub unlock_write()
            unlock(wl)
        End Sub

        Private Sub unlock_read()
            unlock(rl)
        End Sub

        Private Function locked(ByRef i As singleentry) As Boolean
            Return i.in_use()
        End Function

        Private Function write_locked() As Boolean
            Return locked(wl)
        End Function

        Private Function read_locked() As Boolean
            Return locked(rl)
        End Function

        Protected Overridable Function append(ByVal this As valueT, ByVal that As valueT) As valueT
            assert(False)
            Return Nothing
        End Function

        Public Function foreach(ByVal d As _do(Of keyT, valueT, Boolean, Boolean)) As Boolean
            If d Is Nothing OrElse read_locked() Then
                Return False
            Else
                Dim it As map(Of keyT, valueT).iterator = Nothing
                it = m.begin()
                While it <> m.end()
                    Dim goon As Boolean = False
                    If Not (d((+it).first(), (+it).second, goon) AndAlso goon) Then
                        Return Not goon
                    End If
                    it += 1
                End While
                Return True
            End If
        End Function

        Public Function write(ByVal key As keyT, ByVal value As valueT) As Boolean
            If write_locked() Then
                Return False
            Else
                m(key) = append(m(key), value)
                value_size += sizeof(value)
                Return True
            End If
        End Function

        Public Function uniqueWrite(ByVal key As keyT, ByVal value As valueT) As Boolean
            If write_locked() Then
                Return False
            Else
                If seek(key) Then
                    Return False
                Else
                    Return modify(key, value)
                End If
            End If
        End Function

        Public Function delete(ByVal key As keyT) As Boolean
            If write_locked() Then
                Return False
            Else
                Dim it As map(Of keyT, valueT).iterator = Nothing
                it = m.find(key)
                If it = m.end() Then
                    Return False
                Else
                    value_size -= sizeof((+it).second)
                    Return m.erase(it)
                End If
            End If
        End Function

        Public Function modify(ByVal key As keyT, ByVal value As valueT) As Boolean
            Return delete(key) AndAlso write(key, value)
        End Function

        Public Function read(ByVal key As keyT, ByRef value As valueT) As Boolean
            If read_locked() Then
                Return False
            Else
                Dim it As map(Of keyT, valueT).iterator = Nothing
                it = m.find(key)
                If it = m.end() Then
                    Return False
                Else
                    value = (+it).second
                    Return True
                End If
            End If
        End Function

        Public Function seek(ByVal key As keyT) As Boolean
            If read_locked() Then
                Return False
            Else
                Return m.find(key) <> m.end()
            End If
        End Function

        Public Function capacity() As Int64
            Return maxInt64
        End Function

        Public Function valuesize() As Int64
            If isdebugmode() Then
                Dim it As map(Of keyT, valueT).iterator = Nothing
                Dim rtn As Int64 = 0
                it = m.begin()
                While it <> m.end()
                    rtn += sizeof((+it).second)
                    it += 1
                End While
                assert(rtn = value_size)
            End If
            Return value_size
        End Function

        Public Function list(ByRef rtn As vector(Of keyT)) As Boolean
            If read_locked() Then
                Return False
            Else
                vector(Of keyT).initial_instance(rtn)
                Dim it As map(Of keyT, valueT).iterator = Nothing
                it = m.begin()
                While it <> m.end()
                    assert(rtn.push_back((+it).first()))
                    it += 1
                End While
                Return True
            End If
        End Function

        Public Function status(Optional ByRef health_slices As Int64 = Nothing,
                               Optional ByRef all_slices As Int64 = Nothing) As Boolean
            health_slices = 0
            all_slices = 0
            Return True
        End Function

        Public Function open() As Boolean
            Return True
        End Function

        Public Function close() As Boolean
            Return True
        End Function

        Public Function full() As Boolean
            Return False
        End Function

        Public Function health() As Boolean
            Return True
        End Function

        Public Function retire() As Boolean
            m.clear()
            value_size = 0
            Return True
        End Function

        Public Function empty() As Boolean
            Return m.empty()
        End Function

        Protected Overridable Function sizeof(ByVal v As valueT) As Int64
            assert(False)
            Return 0
        End Function

        Public Function sizeof(ByVal key As keyT, ByRef sz As Int64) As Boolean
            If read_locked() Then
                Return False
            Else
                Dim it As map(Of keyT, valueT).iterator = Nothing
                it = m.find(key)
                If it = m.end() Then
                    Return False
                Else
                    sz = sizeof((+it).second)
                    Return True
                End If
            End If
        End Function

        Public Function keycount(ByRef c As Int64) As Boolean
            If read_locked() Then
                Return False
            Else
                c = keycount()
                Return True
            End If
        End Function

        Public Function keycount() As Int64
            Return m.size()
        End Function

        Public Function sync(ByVal host As String, ByVal port As Int32) As Boolean
            Return False
        End Function

        Public Function version() As String
            Return "0"
        End Function

        Public Function lockwrite() As Boolean
            lock_write()
            assert(write_locked())
            Return True
        End Function

        Public Function unlockwrite() As Boolean
            unlock_write()
            assert(Not write_locked())
            Return True
        End Function

        Public Function lockread() As Boolean
            lock_read()
            assert(read_locked())
            Return True
        End Function

        Public Function unlockread() As Boolean
            unlock_read()
            assert(Not read_locked())
            Return True
        End Function

        Public Function lock() As Boolean
            Return lockread() AndAlso lockwrite()
        End Function

        Public Function unlock() As Boolean
            Return unlockread() AndAlso unlockwrite()
        End Function
    End Class
End Namespace
